home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / util / Str.c++ < prev    next >
C/C++ Source or Header  |  1994-08-01  |  15KB  |  673 lines

  1. /*    $Header: /usr/people/sam/fax/util/RCS/Str.c++,v 1.17 1994/02/28 14:24:21 sam Rel $ */
  2. /*
  3.  * Copyright (c) 1990, 1991, 1992, 1993, 1994 Sam Leffler
  4.  * Copyright (c) 1991, 1992, 1993, 1994 Silicon Graphics, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and 
  7.  * its documentation for any purpose is hereby granted without fee, provided
  8.  * that (i) the above copyright notices and this permission notice appear in
  9.  * all copies of the software and related documentation, and (ii) the names of
  10.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  11.  * publicity relating to the software without the specific, prior written
  12.  * permission of Sam Leffler and Silicon Graphics.
  13.  * 
  14.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  15.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  16.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  17.  * 
  18.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  19.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  20.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  22.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  23.  * OF THIS SOFTWARE.
  24.  */
  25. #include "Str.h"
  26. #include <stdlib.h>
  27. #include <ctype.h>
  28.  
  29. #define NUMBUFSIZE 2048
  30. char fxStr::emptyString = '\0';
  31.  
  32. fxStr::fxStr(u_int l)
  33. {
  34.     slength = l+1;
  35.     if (l>0) {
  36.     data = new char[slength];
  37.     } else
  38.     data = &emptyString;
  39.     memset(data,0,slength);
  40. }
  41.  
  42. fxStr::fxStr(const char *s)
  43. {
  44.     u_int l = strlen(s)+1;
  45.     if (l>1) {
  46.     data = new char[l];
  47.     memcpy(data,s,l);
  48.     } else {
  49.     data = &emptyString;
  50.     }
  51.     slength = l;
  52. }
  53.  
  54. fxStr::fxStr(const char *s, u_int len)
  55. {
  56.     if (len>0) {
  57.     data = new char[len+1];
  58.     memcpy(data,s,len);
  59.     } else
  60.     data = &emptyString;
  61.     slength = len+1;
  62.     data[len] = 0;
  63. }
  64.  
  65. fxStr::fxStr(const fxStr&s)
  66. {
  67.     slength = s.slength;
  68.     if (slength > 1) {
  69.     data = new char[slength];
  70.     memcpy(data,s.data,slength);
  71.     } else {
  72.     data = &emptyString;
  73.     }
  74. }
  75.  
  76. fxStr::fxStr(const fxTempStr &t)
  77. {
  78.     slength = t.slength;
  79.     if (t.slength>1) {
  80.     data = new char[slength];
  81.     memcpy(data,t.data,slength);
  82.     } else {
  83.     data = &emptyString;
  84.     }
  85. }
  86.  
  87. fxStr::fxStr(int a, const char * format)
  88. {
  89.     char buffer[NUMBUFSIZE];
  90.     if (!format) format = "%d";
  91.     sprintf(buffer,format,a);
  92.     slength = strlen(buffer) + 1;
  93.     data = new char[slength];
  94.     memcpy(data,buffer,slength);
  95. }
  96.  
  97. fxStr::fxStr(long a, const char * format)
  98. {
  99.     char buffer[NUMBUFSIZE];
  100.     if (!format) format = "%ld";
  101.     sprintf(buffer,format,a);
  102.     slength = strlen(buffer) + 1;
  103.     data = new char[slength];
  104.     memcpy(data,buffer,slength);
  105. }
  106.  
  107. fxStr::fxStr(float a, const char * format)
  108. {
  109.     char buffer[NUMBUFSIZE];
  110.     if (!format) format = "%g";
  111.     sprintf(buffer,format,a);
  112.     slength = strlen(buffer) + 1;
  113.     fxAssert(slength>1, "Str::Str(float): bogus conversion");
  114.     data = new char[slength];
  115.     memcpy(data,buffer,slength);
  116. }
  117.  
  118. fxStr::fxStr(double a, const char * format)
  119. {
  120.     char buffer[NUMBUFSIZE];
  121.     if (!format) format = "%lg";
  122.     sprintf(buffer,format,a);
  123.     slength = strlen(buffer) + 1;
  124.     fxAssert(slength>1, "Str::Str(double): bogus conversion");
  125.     data = new char[slength]; // XXX assume slength>1
  126.     memcpy(data,buffer,slength);
  127. }
  128.  
  129. fxStr::~fxStr()
  130. {
  131.     assert(data);
  132.     if (data != &emptyString) delete data;
  133. }
  134.  
  135. fxStr fxStr::extract(u_int start, u_int chars) const
  136. {
  137.     fxAssert(start+chars<slength, "Str::extract: Invalid range");
  138.     return fxStr(data+start,chars);
  139. }
  140.  
  141. fxStr fxStr::head(u_int chars) const
  142. {
  143.     fxAssert(chars<slength, "Str::head: Invalid size");
  144.     return fxStr(data,chars);
  145. }
  146.  
  147. fxStr fxStr::tail(u_int chars) const
  148. {
  149.     fxAssert(chars<slength, "Str::tail: Invalid size");
  150.     return fxStr(data+slength-chars-1,chars);
  151. }
  152.  
  153. void fxStr::lowercase()
  154. {
  155.     char* cp = data;
  156.     for (int i = slength; i > 0; i--, cp++) {
  157. #ifdef _tolower
  158.     char c = *cp;
  159.     if (isupper(c))
  160.         *cp = _tolower(c);
  161. #else
  162.     *cp = tolower(*cp);
  163. #endif
  164.     }
  165. }
  166.  
  167. void fxStr::raisecase()
  168. {
  169.     char* cp = data;
  170.     for (int i = slength; i > 0; i--, cp++) {
  171. #ifdef _toupper
  172.     char c = *cp;
  173.     if (islower(c))
  174.         *cp = _toupper(c);
  175. #else
  176.     *cp = toupper(*cp);
  177. #endif
  178.     }
  179. }
  180.  
  181. fxStr fxStr::copy() const
  182. {
  183.     return fxStr(data,slength-1);
  184. }
  185.  
  186. void fxStr::remove(u_int start, u_int chars)
  187. {
  188.     fxAssert(start+chars<slength,"Str::remove: Invalid range");
  189.     long move = slength-start-chars;        // we always move at least 1
  190.     assert(move > 0);
  191.     if (slength - chars <= 1) {
  192.     resizeInternal(0);
  193.     slength = 1;
  194.     } else {
  195.     memmove(data+start, data+start+chars, (u_int)move);
  196.     slength -= chars;
  197.     }
  198. }
  199.  
  200. fxStr fxStr::cut(u_int start, u_int chars)
  201. {
  202.     fxAssert(start+chars<slength,"Str::cut: Invalid range");
  203.     fxStr a(data+start, chars);
  204.     remove(start, chars);
  205.     return a;
  206. }
  207.  
  208. void fxStr::insert(const char * v, u_int posn, u_int len)
  209. {
  210.     if (!len) len = strlen(v);
  211.     if (!len) return;
  212.     fxAssert(posn<slength, "Str::insert: Invalid index");
  213.     u_int move = slength - posn;
  214.     u_int nl = slength + len;
  215.     resizeInternal(nl);
  216.     /*
  217.      * When move is one we are always moving \0; but beware
  218.      * that the previous string might have been null before
  219.      * the call to resizeInternal; so set the byte explicitly.
  220.      */
  221.     if (move == 1)
  222.     data[posn+len] = '\0';
  223.     else
  224.     memmove(data+posn+len, data+posn, move);
  225.     memcpy(data+posn, v, len);
  226.     slength = nl;
  227. }
  228.  
  229. void fxStr::insert(char a, u_int posn)
  230. {
  231.     u_int nl = slength + 1;
  232.     resizeInternal(nl);
  233.     long move = (long)slength - (long)posn;
  234.     fxAssert(move>0, "Str::insert(char): Invalid index");
  235.     /*
  236.      * When move is one we are always moving \0; but beware
  237.      * that the previous string might have been null before
  238.      * the call to resizeInternal; so set the byte explicitly.
  239.      */
  240.     if (move == 1)
  241.     data[posn+1] = '\0';
  242.     else
  243.     memmove(data+posn+1, data+posn, (size_t) move);    // move string tail
  244.     data[posn] = a;
  245.     slength = nl;
  246. }
  247.  
  248. void fxStr::resizeInternal(u_int chars)
  249. {
  250.     if (slength > 1) {
  251.     if (chars > 0) {
  252.         if (chars >= slength)
  253.         data = (char *)realloc(data,chars+1);
  254.     } else {
  255.         assert(data != &emptyString);
  256.         free(data);
  257.         data = &emptyString;
  258.     }
  259.     } else {
  260.     assert(data == &emptyString);
  261.     if (chars)
  262.         data = new char[chars+1];
  263.     }
  264. }
  265.  
  266.  
  267. void fxStr::resize(u_int chars, fxBool)
  268. {
  269.     resizeInternal(chars);
  270.     if (chars>=slength)
  271.     memset(data+slength, 0, chars+1-slength);
  272.     slength = chars+1;
  273.     data[chars] = 0;
  274. }
  275.  
  276. void fxStr::setMaxLength(u_int len)
  277. {
  278.     if (slength>1) resizeInternal(fxmax(len,slength-1));
  279. }
  280.  
  281. void fxStr::operator=(const fxTempStr& s)
  282. {
  283.     resizeInternal(s.slength-1);
  284.     memcpy(data,s.data,s.slength);
  285.     slength = s.slength;
  286. }
  287.  
  288. void fxStr::operator=(const fxStr& s)
  289. {
  290.     resizeInternal(s.slength-1);
  291.     memcpy(data,s.data,s.slength);
  292.     slength = s.slength;
  293. }
  294.  
  295. void fxStr::operator=(const char *s)
  296. {
  297.     u_int nl = strlen(s) + 1;
  298.     resizeInternal(nl-1);
  299.     slength = nl;
  300.     memcpy(data,s,slength);
  301. }
  302.  
  303. void fxStr::append(const char * s, u_int l)
  304. {
  305.     if (!l) l = strlen(s);
  306.     if (!l) return;
  307.     u_int nl = slength + l;
  308.     resizeInternal(nl-1);
  309.     memcpy(data+slength-1, s, l);
  310.     slength = nl;
  311.     data[slength-1] = 0;
  312. }
  313.  
  314. void fxStr::append(char a)
  315. {
  316.     resizeInternal(slength);
  317.     slength++;
  318.     data[slength-2] = a;
  319.     data[slength-1] = 0;
  320. }
  321.  
  322. fxBool operator==(const fxStr& a,const fxStr& b)
  323. {
  324.     return (a.slength == b.slength) && (memcmp(a.data,b.data,a.slength) == 0);
  325. }
  326.  
  327. fxBool operator==(const fxStr& a,const char* b)
  328. {
  329.     return (a.slength == strlen(b)+1) && (memcmp(a.data,b,a.slength) == 0);
  330. }
  331.  
  332. fxBool operator==(const char* b, const fxStr& a)
  333. {
  334.     return (a.slength == strlen(b)+1) && (memcmp(a.data,b,a.slength) == 0);
  335.  
  336. fxBool operator!=(const fxStr& a,const fxStr& b)
  337. {
  338.     return (a.slength != b.slength) || (memcmp(a.data,b.data,a.slength) != 0);
  339. }
  340.  
  341. fxBool operator!=(const fxStr& a,const char* b)
  342. {
  343.     return (a.slength != strlen(b)+1) || (memcmp(a.data,b,a.slength) != 0);
  344. }
  345.  
  346. fxBool operator!=(const char* b, const fxStr& a)
  347. {
  348.     return (a.slength != strlen(b)+1) || (memcmp(a.data,b,a.slength) != 0);
  349.  
  350. fxBool operator>=(const fxStr& a,const fxStr& b)
  351. {
  352.     return strcmp(a,b) >= 0;
  353. }
  354.  
  355. fxBool operator>=(const fxStr& a,const char* b)
  356. {
  357.     return strcmp(a,b) >= 0;
  358. }
  359.  
  360. fxBool operator>=(const char* a, const fxStr& b)
  361. {
  362.     return strcmp(a,b) >= 0;
  363.  
  364. fxBool operator>(const fxStr& a,const fxStr& b)
  365. {
  366.     return strcmp(a,b) > 0;
  367. }
  368.  
  369. fxBool operator>(const fxStr& a,const char* b)
  370. {
  371.     return strcmp(a,b) > 0;
  372. }
  373.  
  374. fxBool operator>(const char* a, const fxStr& b)
  375. {
  376.     return strcmp(a,b) > 0;
  377.  
  378. fxBool operator<=(const fxStr& a,const fxStr& b)
  379. {
  380.     return strcmp(a,b) <= 0;
  381. }
  382.  
  383. fxBool operator<=(const fxStr& a,const char* b)
  384. {
  385.     return strcmp(a,b) <= 0;
  386. }
  387.  
  388. fxBool operator<=(const char* a, const fxStr& b)
  389. {
  390.     return strcmp(a,b) <= 0;
  391.  
  392. fxBool operator<(const fxStr& a,const fxStr& b)
  393. {
  394.     return strcmp(a,b) < 0;
  395. }
  396.  
  397. fxBool operator<(const fxStr& a,const char* b)
  398. {
  399.     return strcmp(a,b) < 0;
  400. }
  401.  
  402. fxBool operator<(const char* a, const fxStr& b)
  403. {
  404.     return strcmp(a,b) < 0;
  405.  
  406. int compare(const fxStr&a, const fxStr&b)
  407. {
  408.     return strcmp(a,b);
  409. }
  410.  
  411. int compare(const fxStr&a, const char*b)
  412. {
  413.     return strcmp(a,b);
  414. }
  415.  
  416. int compare(const char *a, const char *b)
  417. {
  418.     return strcmp(a,b);
  419. }
  420.  
  421.  
  422. static int quickFind(char a, const char * buf, u_int buflen)
  423. {
  424.     while (buflen--)
  425.     if (*buf++ == a) return 1;
  426.     return 0;
  427. }
  428.  
  429. u_int fxStr::next(u_int posn, char a) const
  430. {
  431.     fxAssert(posn<slength, "Str::next: invalid index");
  432.     char * buf = data+posn;
  433.     u_int counter = slength-1-posn;
  434.     while (counter--) {
  435.     if (*buf == a) return (buf-data);
  436.     buf++;
  437.     }
  438.     return slength-1;
  439. }
  440.  
  441. u_int fxStr::next(u_int posn, const char * c, u_int clen) const
  442. {
  443.     fxAssert(posn<slength, "Str::next: invalid index");
  444.     char * buf = data + posn;
  445.     u_int counter = slength-1-posn;
  446.     if (!clen) clen = strlen(c);
  447.     while (counter--) {
  448.     if (quickFind(*buf,c,clen)) return (buf-data);
  449.     buf++;
  450.     }
  451.     return slength-1;
  452. }
  453.  
  454. u_int fxStr::nextR(u_int posn, char a) const
  455. {
  456.     fxAssert(posn<slength, "Str::nextR: invalid index");
  457.     char * buf = data + posn - 1;
  458.     u_int counter = posn;
  459.     while (counter--) {
  460.     if (*buf == a) return (buf-data+1);
  461.     buf--;
  462.     }
  463.     return 0;
  464. }
  465.  
  466. u_int fxStr::nextR(u_int posn, const char * c, u_int clen) const
  467. {
  468.     fxAssert(posn<slength, "Str::nextR: invalid index");
  469.     char * buf = data + posn - 1;
  470.     u_int counter = posn;
  471.     if (!clen) clen = strlen(c);
  472.     while (counter--) {
  473.     if (quickFind(*buf,c,clen)) return (buf-data+1);
  474.     buf--;
  475.     }
  476.     return 0;
  477. }
  478.  
  479. u_int fxStr::skip(u_int posn, char a) const
  480. {
  481.     fxAssert(posn<slength, "Str::skip: invalid index");
  482.     char * buf = data+posn;
  483.     u_int counter = slength-1-posn;
  484.     while (counter--) {
  485.     if (*buf != a) return (buf-data);
  486.     buf++;
  487.     }
  488.     return slength-1;
  489. }
  490.  
  491. u_int fxStr::skip(u_int posn, const char * c, u_int clen) const
  492. {
  493.     fxAssert(posn<slength, "Str::skip: invalid index");
  494.     char * buf = data + posn;
  495.     u_int counter = slength-1-posn;
  496.     if (!clen) clen = strlen(c);
  497.     while (counter--) {
  498.     if (!quickFind(*buf,c,clen)) return (buf-data);
  499.     buf++;
  500.     }
  501.     return slength-1;
  502. }
  503.  
  504. u_int fxStr::skipR(u_int posn, char a) const
  505. {
  506.     fxAssert(posn<slength, "Str::skipR: invalid index");
  507.     char * buf = data + posn - 1;
  508.     u_int counter = posn;
  509.     while (counter--) {
  510.     if (*buf != a) return (buf-data+1);
  511.     buf--;
  512.     }
  513.     return 0;
  514. }
  515.  
  516. u_int fxStr::skipR(u_int posn, const char * c, u_int clen) const
  517. {
  518.     fxAssert(posn<slength, "Str::skipR: invalid index");
  519.     char * buf = data + posn - 1;
  520.     u_int counter = posn;
  521.     if (!clen) clen = strlen(c);
  522.     while (counter--) {
  523.     if (!quickFind(*buf,c,clen)) return (buf-data+1);
  524.     buf--;
  525.     }
  526.     return 0;
  527. }
  528.  
  529. fxStr fxStr::token(u_int & posn, const char * delim, u_int dlen) const
  530. {
  531.     fxAssert(posn<slength, "Str::token: invalid index");
  532.     if (!dlen) dlen = strlen(delim);
  533.     u_int end = next(posn, delim, dlen);
  534.     u_int old = posn;
  535.     posn = skip(end, delim, dlen);
  536.     return extract(old,end-old);
  537. }
  538.  
  539. fxStr fxStr::token(u_int & posn, char a) const
  540. {
  541.     fxAssert(posn<slength, "Str::token: invalid index");
  542.     u_int end = next(posn, a);
  543.     u_int old = posn;
  544.     posn = skip(end, a);
  545.     return extract(old,end-old);
  546. }
  547.  
  548. fxStr fxStr::tokenR(u_int & posn, const char * delim, u_int dlen) const
  549. {
  550.     fxAssert(posn<slength, "Str::tokenR: invalid index");
  551.     if (!dlen) dlen = strlen(delim);
  552.     u_int begin = nextR(posn, delim, dlen);
  553.     u_int old = posn;
  554.     posn = skipR(begin, delim, dlen);
  555.     return extract(begin, old-begin);
  556. }
  557.  
  558. fxStr fxStr::tokenR(u_int & posn, char a) const
  559. {
  560.     fxAssert(posn<slength, "Str::tokenR: invalid index");
  561.     u_int begin = nextR(posn, a);
  562.     u_int old = posn;
  563.     posn = skipR(begin, a);
  564.     return extract(begin,old-begin);
  565. }
  566.  
  567. u_long fxStr::hash() const
  568. {
  569.     char * elementc = data;
  570.     u_int slen = slength - 1;
  571.     u_long k = 0;
  572.     if (slen < 2*sizeof(k)) {
  573.     if (slen <= sizeof(k)) {
  574.         memcpy((char *)&k + (sizeof(k) - slen), elementc, slen);
  575.         k<<=3;
  576.     } else {
  577.         memcpy((char *)&k + (sizeof(k)*2 - slen), elementc, slen-sizeof(k));
  578.         k<<=3;
  579.         k ^= *(u_long *)elementc;
  580.     }
  581.     } else {
  582.     k = *(u_long *)(elementc + sizeof(k));
  583.     k<<=3;
  584.     k ^= *(u_long *)elementc;
  585.     }
  586.     return k;
  587. }
  588.  
  589. //--- concatenation support ----------------------------------
  590.  
  591. fxTempStr::fxTempStr(const char *d1, u_int l1, const char *d2, u_int l2)
  592. {
  593.     slength = l1 + l2 + 1;
  594.     if (slength <= sizeof(indata)) {
  595.     data = &indata[0];
  596.     } else {
  597.     data = new char[slength];
  598.     }
  599.     memcpy(data,d1,l1);
  600.     memcpy(data+l1,d2,l2);
  601.     data[l1+l2] = 0;
  602. }
  603.  
  604. fxTempStr::fxTempStr(fxTempStr const &other)
  605. {
  606.     slength = other.slength;
  607.     if (slength <= sizeof (indata)) {
  608.     data = &indata[0];
  609.     } else {
  610.     data = new char[slength];
  611.     }
  612.     memcpy(data, other.data, slength);
  613.     data[slength] = 0;
  614. }
  615.  
  616. fxTempStr::~fxTempStr()
  617. {
  618.     if (data != indata) delete data;
  619. }
  620.  
  621. fxTempStr& operator|(const fxTempStr& ts, const fxStr &b)
  622. {
  623.     return ((fxTempStr &)ts).concat(b.data, b.slength-1);
  624. }
  625.  
  626. fxTempStr& operator|(const fxTempStr& ts, const char *b)
  627. {
  628.     return ((fxTempStr &)ts).concat(b, strlen(b));
  629. }
  630.  
  631. fxTempStr& fxTempStr::concat(const char* b, u_int bl)
  632. {
  633.     if (slength <= sizeof(indata)) {
  634.     // Current temporary is in the internal buffer.  See if the
  635.     // concatenation will fit too.
  636.     if (slength + bl > sizeof(indata)) {
  637.         // Have to malloc.
  638.         data = (char*) malloc(slength + bl);
  639.         memcpy(data, indata, slength - 1);
  640.     }
  641.     } else {
  642.     // Temporary is already too large.
  643.     data = (char*) realloc(data, slength + bl);
  644.     }
  645.  
  646.     // concatenate data
  647.     memcpy(data+slength-1, b, bl);
  648.     slength += bl;
  649.     data[slength-1] = 0;
  650.     return *this;
  651. }
  652.  
  653. fxTempStr operator|(const fxStr &a, const fxStr &b)
  654. {
  655.     return fxTempStr(a.data, a.slength-1, b.data, b.slength-1);
  656. }
  657.  
  658. fxTempStr operator|(const fxStr &a, const char *b)
  659. {
  660.     return fxTempStr(a.data, a.slength-1, b, strlen(b));
  661. }
  662.  
  663. fxTempStr operator|(const char *a, const fxStr &b)
  664. {
  665.     return fxTempStr(a, strlen(a), b.data, b.slength-1);
  666. }
  667.